import {
  ComponentFactoryResolver,
  Directive,
  ElementRef,
  Input,
  Renderer2,
  ViewContainerRef,
  AfterViewInit,
  OnChanges,
  SimpleChanges,
} from '@angular/core';

import { Direction } from '../shared/shared';
import { TooltipComponent } from './tooltip.component';

@Directive({
  selector: '[fuiTooltip]',
})
export class TooltipDirective implements OnChanges, AfterViewInit {
  tooltipComponent: TooltipComponent;

  /**
   * Tooltip text value.
   * Support multiple lines by useing '\n' in the string.
   */
  @Input('fuiTooltip') tooltip: string;

  /** Tooltip placement. */
  @Input('fuiTooltipPlacement') placement: Direction;

  constructor(
    public elementRef: ElementRef,
    public hostView: ViewContainerRef,
    public resolver: ComponentFactoryResolver,
    public renderer: Renderer2,
  ) {}

  ngOnChanges(changes: SimpleChanges) {
    if (!this.tooltipComponent) {
      this.initTooltipComponent();
    }
    const {tooltip, placement, fuiTooltipPos} = changes;
    if (tooltip && tooltip.currentValue) {
      this.tooltipComponent.tooltip = tooltip.currentValue;
    }
    if (placement && placement.currentValue) {
      this.tooltipComponent.placement = placement.currentValue;
    }
  }

  ngAfterViewInit() {
    this.renderer.listen(this.elementRef.nativeElement, 'mouseenter', () => this.show());
    this.renderer.listen(this.elementRef.nativeElement, 'mouseleave', () => this.hide());
  }

  initTooltipComponent() {
    const factory = this.resolver.resolveComponentFactory(TooltipComponent);
    const tooltipComponent = this.hostView.createComponent(factory);
    this.tooltipComponent = tooltipComponent.instance;
    this.renderer.removeChild(this.renderer.parentNode(this.elementRef.nativeElement), tooltipComponent.location.nativeElement);
    this.tooltip = this.tooltip;
    this.placement = this.placement;
    this.tooltipComponent.setOverlayOrigin(this);
  }

  private show() {
    this.tooltipComponent.show();
  }

  private hide() {
    this.tooltipComponent.hide();
  }
}
